﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace NMemcached.Client
{
    /// <summary>
    /// Serializes and deserializes byte sequences using the BinaryFormatter
    /// </summary>
    public class BinarySerializer : ISerializer
    {
        static BinarySerializer()
        {
        }

        /// <summary>
        /// Initializes a new instance of the BinarySerializer
        /// </summary>
        public BinarySerializer()
        {
        }

        /// <summary>
        /// Serializes an object into a sequence of bytes using the BinaryFormatter
        /// </summary>
        /// <param name="data">The data to serialize</param>
        /// <returns>The serialized object as a sequence of bytes</returns>
        public virtual byte[] Serialize(object data)
        {
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }

            byte[] serialized = null;

            using (MemoryStream outputStream = new MemoryStream())
            {
                BinaryFormatter formatter = new BinaryFormatter();
                formatter.Serialize(outputStream, data);
                serialized = outputStream.ToArray();
                return serialized;
            }
        }

        /// <summary>
        /// Deserializes a sequence of bytes into a collection of objects using the BinaryFormatter
        /// </summary>
        /// <param name="data">The sequence of bytes to deserialize</param>
        /// <returns>A collection of objects deserialized from the sequence of bytes</returns>
        public virtual IEnumerable<object> Deserialize(byte[] data)
        {
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }

            using (MemoryStream inputStream = new MemoryStream(data))
            {
                inputStream.Position = 0;

                IList<object> items = new List<object>();
                BinaryFormatter formatter = new BinaryFormatter();

                //Get all objects from the stream
                object current = null;
                while (inputStream.Position < inputStream.Length)
                {
                    current = formatter.Deserialize(inputStream);
                    items.Add(current);
                }

                return items;
            }
        }
    }
}
